let actionTimer = null;
function initCallbackFunc(msg, roomIndex, deskIndex, players) {
	showMsgOnTitle(msg);
	if (roomIndex > -1) {
		user.roomIndex = roomIndex;
	}
	if (deskIndex > -1) {
		user.deskIndex = deskIndex;
	}
	if (typeof players == 'object') {
		user.players = players;
	}
};

function join() {
	socket.emit('join', initCallbackFunc);
	renderStartBtnWaiting();
}

function createRoom() {
	socket.emit('createRoom', initCallbackFunc);
	disableAllBtn();
}

function joinRoom() {
	socket.emit('joinRoom', roomNumInp.value, initCallbackFunc);
	disableAllBtn();
}

// 发送私聊消息
function sendMsg() {
	socket.emit('privateMsg', sendSid, sendMsgInp.value);
	clearMsgInp();
}
// 接收私聊消息
socket.on('privateMsg', (name, msg) => {
	console.log(`${name}私信:${msg}`);
	if (/^[0-9]{10,}$/.test(msg)) {
		// 如果是10位以上的连续数字，自动填充到房号里
		roomNumInp.value = msg;
	}
	// 渲染消息盒子
	let div = document.createElement('div');
	div.classList.add('onlineMsg');
	div.innerText = `${name}私信:${msg}`;
	div.style.bottom = `${128 - document.querySelectorAll('.onlineMsg').length * 32}px`;
	document.body.appendChild(div);
	// 设置定时器，2.5s后移除消息盒子，更新其他盒子的位置
	setTimeout(() => {
		div.remove();
		let all = document.querySelectorAll('.onlineMsg');
		for (let i = 0; i < all.length; i++) {
			all[i].style.bottom = `${(all.length + 1 - i) * 32}px`;
		}
	}, 2700)
})

socket.on('getOnlinePlayer', msg => {
	if (msg.length > 0) {
		onlinePlayers = msg;
		// console.log(onlinePlayers);
		// 更新在线玩家视图
		updateOnlinePlayers();
	}
});

socket.on('personOffline', (msg, deskIndex, players) => {
	showMsgOnTitle(msg);
	if (deskIndex > -1) {
		user.deskIndex = deskIndex;
	}
	if (typeof players == 'object') {
		user.players = players;
		renderPlayersName();
	}
});

socket.on('room', (msg, players) => {
	showMsgOnTitle(msg);
	if (typeof players == 'object') {
		user.players = players;
		renderPlayersName();
	}
})

socket.on('game', (msg, activePlayerDeskIndex) => {
	showMsgOnTitle(msg)
	if (activePlayerDeskIndex > -1) {
		gameInfo.activePlayerDeskIndex = activePlayerDeskIndex;
		removeStartBtnWaiting();
	}
});

socket.on('initHandCard', (handCard, restCard, deadCards) => {
	initHandCard(handCard, restCard, deadCards);
});
function initHandCard(handCard, restCard, deadCards) {
	user["handCard"] = handCard;
	// 算分
	renderHiddenScore(user["handCard"]);
	// 看牌
	renderHandCard();
	gameInfo["restCard"] = restCard;
	gameInfo["deadCards"] = deadCards;
	// 渲染抽牌堆和弃牌堆
	initRestCardRender();
	initDeadCardRender();
	// 默认当前是打出模式
	user.justConsume = true;
	// 开启一次普通回合循环（允许活动玩家做行动，非活动玩家不动）
	gameLoop();
}
function gameAgain() {
	loginContainer.style.display = "none";
	// 清除所有玩家的手牌区和桌面分
	clearHandCardAndScore();
	// 清除中央牌区、抽牌堆、弃牌堆
	clearCardArea();
	socket.emit('gameAgain', user.roomIndex, user.deskIndex);
}
// 处理视图渲染
socket.on('updateView', (mode, params) => {
	switch (mode) {
		case 'win':
			showMsgOnTitle(`恭喜玩家 ${user.players[params].name} 取得胜利`)
			// 弹出一个祝贺获胜或提示惜败的图片
			// 点击再来一局按钮，清除当前对局的数据，等待服务器重新发送初始手牌
			renderGameOverBtn();
			break;
		case 'lost':
			showMsgOnTitle(`你输了`);
			renderGameOverBtn();
			break;
		case 'updateCardArea':
			addCardToArea(parseInt(params));
			break;
		case 'updatePlayerScore':
			// 客户端不保存分数,因此直接渲染视图
			renderScore(params[0], params[1], params[2], params[3]);
			break;
		case 'updateCardHeap':
			initRestCardRender();
			if (gameInfo.deadCards.length > deadCards.children.length) {
				// 说明需要往弃牌堆增加那一张卡
				addCardToDeadCardHeap(gameInfo.deadCards[gameInfo.deadCards.length - 1]);
				initDeadCardRender();
			} else if (gameInfo.deadCards.length < deadCards.children.length) {
				if (gameInfo.deadCards.length > 0) {
					removeCardFromDeadCardHeap();
				}
				initDeadCardRender();
			}
			break;
		case 'updateActivePlayerHandCard':
			// 其一,活动玩家失去一张未翻面的手牌
			// 其三,活动玩家发起交易,失去一张未翻面的手牌
			if ((params == 'consume') || (params == 'deliver')) {
				removeCardFromPlayerHand(gameInfo.activePlayerDeskIndex);
			}
			// 其二,活动玩家获得一张未翻面的手牌
			if (params[0] == 'draw') {
				addCardToPlayerHand(gameInfo.activePlayerDeskIndex, (gameInfo.activePlayerDeskIndex == user.deskIndex ? params[1] : 31));
			}
			// 其三,交易后的视图更新
			if (params[0] == 'trade') {
				if (gameInfo.activePlayerDeskIndex == user.deskIndex) {
					// 发起交易方
					addCardToPlayerHand(user.deskIndex, user.handCard[user.handCard.length - 1]);
					removeCardFromPlayerHand(user.deskIndex, params[1])
				} else if (gameInfo.activePlayerDeskIndex == ((user.deskIndex - 1) % 3)) {
					// 接收交易方
					addCardToPlayerHand(user.deskIndex, user.handCard[user.handCard.length - 1]);
					removeCardFromPlayerHand(user.deskIndex, params[2]);
					// 发起交易方失去一张牌
					addCardToPlayerHand(gameInfo.activePlayerDeskIndex, 31);
				} else if (gameInfo.activePlayerDeskIndex == ((user.deskIndex + 1) % 3)) {
					// 第三方玩家
					addCardToPlayerHand(gameInfo.activePlayerDeskIndex, 31);
					// 中央牌区移除一张卡背
				}
				removeLastCardFromArea();
			}
			// 其四,交易触发白嫖后的视图更新
			if (params[0] == 'trade_not_ok') {
				if (params[1] == user.deskIndex) {
					// 接收交易方
					showMsgOnTitle(`下家吃牌,${params[2] % 10 == 0 ? params[2] : ''}变为明牌`)
					// 之前接受交易时移除了牌，变明牌时这里要添加回来
					// 创建明牌
					addCardToPlayerHand(params[1], params[2]);
					// 明牌进入冷却
					banCard(params[2]);
				} else {
					// 先移除一张卡背
					removeCardFromPlayerHand(params[1]);
					// 再创建明牌加入到回应交易方的手牌中
					addCardToPlayerHand(params[1], params[2]);
				}
				removeLastCardFromArea();
			}
			// 其五,交易后触发剥削的视图更新
			if (params[0] == 'trade_ok') {
				if (params[1] == user.deskIndex) {
					// 接收交易方
					showMsgOnTitle("上家吃牌");
					addCardToPlayerHand(params[1], params[2])
				}
				removeLastCardFromArea();
			}
			// 其六,强制交易后触发的视图更新
			if (params[0] == 'request') {
				console.log(params);
				if (gameInfo.activePlayerDeskIndex == user.deskIndex) {
					// 发起交易方移除自己的交易牌（可能会重复移除！）
					removeCardFromPlayerHand(user.deskIndex, params[1]);
					// 被强制交易方得到一张卡背
					addCardToPlayerHand(params[3]);
					// 被交易方移除他的明牌
					removeCardFromPlayerHand(params[3], params[2]);
				} else if (params[3] == user.deskIndex) {
					// 被强制接收交易方如果接收的交易牌是万能牌，则渲染万能牌变化后的牌 params[3]
					if (params[1] % 10 == 0) {
						addCardToPlayerHand(user.deskIndex, params[4]);
					} else {
						addCardToPlayerHand(user.deskIndex, params[1]);
					}
					// 被交易方移除他的明牌
					removeCardFromPlayerHand(user.deskIndex, params[2]);
					// 发起强制交易方移除他的一张牌
					removeCardFromPlayerHand(gameInfo.activePlayerDeskIndex);
				} else {
					// 第三方玩家
					removeCardFromPlayerHand(gameInfo.activePlayerDeskIndex);
					removeCardFromPlayerHand(params[3], params[2])
					addCardToPlayerHand(params[3], 31);
				}
			}
			break;
		case 'showHiddenScore':
			console.log(params);
			renderPlayerHiddenScore(parseInt(params[0]), params[1]);
			break;
		default:
			break;
	}
})
// 处理当前玩家应知道的游戏数据
socket.on('changeActivePlayer', (mode, params) => {
	switch (mode) {
		case 'afterConsume':
		case 'afterRequest':
		case 'afterDeliver':
			// 从手牌移除这张卡
			user.handCard.splice(user.handCard.indexOf(parseInt(params)), 1);
			break;
		case 'afterDraw':
			user.handCard.push(parseInt(params[0]));
			gameInfo.restCard = parseInt(params[1]);
			break;
		case 'afterTrade':
			console.log(params);
			// 从手牌移除交易卡 params[0] 是发起交易方的交易牌
			user.handCard.splice(user.handCard.indexOf(parseInt(params[gameInfo.activePlayerDeskIndex == user.deskIndex ? 0 : 1])), 1);
			// 获得新的交易卡,如果有传第三个参数,表示上家的强制交易时使用的是万能卡,进入被强制交易的玩家手牌区时变化为新的牌 params[3]
			user.handCard.push(parseInt(params[gameInfo.activePlayerDeskIndex == user.deskIndex ? 1 : (params[2] > 0 ? 2 : 0)]));
			break;
		case 'afterTradeOk':
			console.log(params);
			// 从手牌移除交易卡
			user.handCard.splice(user.handCard.indexOf(parseInt(params[0])), 1, parseInt(params[1]));
			break;
		case 'canPlayBanCard':
			// 能打出明牌了
			canPlayBanCard(params);
			break;
		case 'superCardTransfrom':
			console.log("万能牌变化");
			console.log(params);
			if (params[1] > 0) {
				user.handCard.splice(user.handCard.indexOf(parseInt(params[0])), 1, params[1])
			}
			break;
		default:
			break;
	}
})
// 处理所有玩家都应知道的游戏数据
socket.on('changePlayer', (mode, params) => {
	switch (mode) {
		case 'afterConsume':
		case 'afterRequest':
		case 'afterDeliver':
			// 抽牌堆数量变化
			gameInfo.restCard = parseInt(params[0]);
			if (params[1] == 31) {
				// 万能牌进入弃牌堆，清空弃牌堆
				gameInfo.deadCards = [];
			} else if (params[1] > 0 && params[1] < 30) {
				// 弃牌堆多一张
				gameInfo.deadCards.push(parseInt(params[1]))
			}
			break;
		case 'afterDraw':
			gameInfo.restCard = parseInt(params);
			break;
		case 'afterDecompose':
			gameInfo.deadCards.pop();
			break;
		default:
			break;
	}
})
// 处理游戏逻辑
socket.on("playing", (mode, userDeskIndex) => {
	switch (mode) {
		case 'nextPlayer':
			gameInfo.activePlayerDeskIndex = userDeskIndex;
			gameLoop();
			break;
		case 'chooseReply':
			// 需要从手牌中选择一张回复上家
			gameLoop('choose');
			break;
		default:
			break;
	}
})
function canPlay() {
	return (gameInfo.activePlayerDeskIndex == user.deskIndex);
}
function removeAllActionListener() {
	if (user.handCard.length > 0) {
		for (let i = 0; i < hands[2].children.length; i++) {
			const card = hands[2].children[i];
			card.removeEventListener('click', handleCardClick);
		}
	}
	confirmBtn.removeEventListener('click', handleCardButtonClick);
	restCards.removeEventListener('click', drawCard);
	deadCards.removeEventListener('click', decomposeCard);
}
function removeChooseListener() {
	if (user.handCard.length > 0) {
		for (let i = 0; i < hands[2].children.length; i++) {
			const card = hands[2].children[i];
			card.removeEventListener('click', handleCardClick);
		}
	}
}
function checkChoose() {
	if (user.handCard.length > 0) {
		for (let i = 0; i < hands[2].children.length; i++) {
			const card = hands[2].children[i];
			if (!card.classList.contains('banCard')) {
				card.addEventListener('click', handleCardClick);
			}
		}
	}
}
function checkAction() {
	console.log(user.handCard);
	// 手牌>0张时，能消费
	if (user.handCard.length > 0) {
		for (let i = 0; i < hands[2].children.length; i++) {
			const card = hands[2].children[i];
			if (!card.classList.contains('banCard')) {
				card.addEventListener('click', handleCardClick);
			}
		}
		// 能交易
		if (user.handCard.length > 0 && hands[1].childElementCount > 0) {
			confirmBtn.addEventListener('click', handleCardButtonClick);
		} else {
			showMsgOnTitle('下家无手牌,不能拼点');
		}
	}

	if (gameInfo.restCard > 0) {
		// 抽牌堆>0能生产
		restCards.addEventListener('click', drawCard);
	}
	if (gameInfo.deadCards.length > 0) {
		// 弃牌堆>0能分解
		deadCards.addEventListener('click', decomposeCard);
	}
}
// 显示当前是谁的回合，轮到当前玩家时，打开绑定事件监听器允许行动
// 否则移除事件监听器
function gameLoop(mode) {
	if (mode == 'choose') {
		// 允许非活动玩家在4秒内进行选择
		checkChoose();
		if (!actionTimer) {
			actionTimer = setTimeout(() => {
				// 清定时器
				clearTimeout(actionTimer);
				showMsgOnTitle("你的回合已结束1");
				// removeChooseListener();
			}, 4000);
		}
	} else {
		if (canPlay()) {
			// 允许活动玩家在9秒内进行活动
			checkAction();
			if (!actionTimer) {
				actionTimer = setTimeout(() => {
					// 清定时器
					clearTimeout(actionTimer);
					showMsgOnTitle("你的回合已结束2");
					// removeAllActionListener();
				}, 9000);
			}
		} else {
			// 非活动玩家就干等着
			clearTimeout(actionTimer);
			removeAllActionListener();

		}
		showMsgOnTitle(`当前是${user.players[gameInfo.activePlayerDeskIndex].name}的回合`)
	}
	renderActivePlayerStyle();
}
function handleCardClick(e) {
	e.preventDefault();
	e.stopPropagation();
	let cardNum = null;
	// 在自己的回合
	if (canPlay()) {
		cardNum = parseInt(e.target.dataset.index);
		// 直接打出
		if (user.justConsume && (user.handCard.indexOf(cardNum) > -1)) {
			if (cardNum % 10 == 0) {
				showMsgOnTitle("万能牌不能直接打出");
				return;
			}
			// 消费
			console.log(`从手牌打出${cardNum}`);
			socket.emit('playing', 'consume', user.roomIndex, user.deskIndex, cardNum)
			// 点击的打出卡,从手牌区消失
			e.target.remove();
			// 清定时器
			clearTimeout(actionTimer);
			removeAllActionListener();
		} else {
			if (user.curChooseCard > 0) {
				console.log(`指定${cardNum}交换${user.curChooseCard}`);
				// 发起指定交易,不用等下家接收
				socket.emit('playing', 'request', user.roomIndex, user.deskIndex, [cardNum, user.curChooseCard], function (flag) {
					if (flag) {
						// 清定时器
						clearTimeout(actionTimer);
						removeAllActionListener();
					} else {
						showMsgOnTitle('你选择的牌分值小于明牌,不能拼点,请重新选择');
					}
				})
			} else {
				if (cardNum % 10 == 0) {
					showMsgOnTitle("万能牌不能发起主动拼点");
					return;
				}
				// 发起普通交易,等下家接收
				socket.emit('playing', 'deliver', user.roomIndex, user.deskIndex, cardNum)
				// 清定时器
				clearTimeout(actionTimer);
				removeAllActionListener();
				// 客户端自己移除视图了,服务器会操纵客户端的数据层改变
				removeCardFromPlayerHand(user.deskIndex, cardNum);
				user.curChooseCard = -1;
			}
		}
	} else {
		cardNum = parseInt(e.target.dataset.index);
		// 不在自己的回合却能点击卡，说明是想回应交易
		socket.emit('playing', 'trade', user.roomIndex, user.deskIndex, cardNum)
		// 清定时器
		clearTimeout(actionTimer);
		removeAllActionListener();
		// 客户端自己移除视图了,服务器会操纵客户端的数据层改变
		removeCardFromPlayerHand(user.deskIndex, cardNum);
	}
	shua.play();
}

function handleCardButtonClick(e) {
	e.preventDefault();
	e.stopPropagation();
	user.justConsume = !user.justConsume;
	// 改变样式
	renderConfirmBtnText();
}

// 点击抽牌堆，生产
function drawCard() {
	console.log("draw a card");
	// 这个房间这个下标的玩家要采集一张牌
	socket.emit('playing', 'draw', user.roomIndex, user.deskIndex)
	// 清定时器
	clearTimeout(actionTimer);
	removeAllActionListener();
}

// 点击弃牌堆，分解
function decomposeCard() {
	console.log("decompose a card");
	// 这个房间这个下标的玩家要分解一张牌
	socket.emit('playing', 'decompose', user.roomIndex, user.deskIndex)
	// 清定时器
	clearTimeout(actionTimer);
	removeAllActionListener();
}
